package cn.tedu._07springaop.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import java.util.Arrays;

/**
 *
 * 日志功能的切面类
 * @Aspect
 *   标识该类是一个切面类
 */
@Aspect
@Component
public class LogAspect {
    @Pointcut(value = "execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))")
    public void doTime(){};

//    /**@Before前置通知
//     * 另外两个粗粒度的方法
//     * @Before(value=bean(bean对象的名字[首字母小写]))
//     * @Before(value=within(包名.类名表达式))
//     */
//    @Before(value = "doTime()")
//    public void beforeMethod(JoinPoint joinPoint){
//        String name = joinPoint.getSignature().getName();
//        String args=Arrays.toString(joinPoint.getArgs());
//        System.out.println("前置通知:"+name+"方法开始,参数为:"+args);
//    }
//
//    /**
//     * 2.后置通知:
//     *   2.1目标方法彻底结束[正常结束和异常结束]后执行
//     *   2.2后置通知没有权限获取目标方法的返回值
//     * @param joinPoint
//     */
//    @After(value = "doTime()")
//    public void afterMethod(JoinPoint joinPoint){
//        String name = joinPoint.getSignature().getName();
//        System.out.println("后置通知:"+name+"方法彻底结束");
//    }
//    /**
//     * 3.返回通知
//     *   3.1目标方法正常结束后执行
//     *   3.2有权限获取目标方法的返回值
//     */
//    @AfterReturning(value = "doTime()",returning = "result")
//    public void afterReturningMethod(JoinPoint joinPoint,Object result){
//        String name = joinPoint.getSignature().getName();
//        System.out.println("返回通知:"+name+"方法执行结束,结果为" +result);
//    }
//    /**
//     * 4.异常通知
//     *   4.1目标方法抛出异常时执行
//     *   4.2异常通知有权获取异常对象
//     */
//    @AfterThrowing(value = "doTime()",throwing = "ex")
//    public void afterThrowingMethod(JoinPoint joinPoint,Throwable ex){
//        String name = joinPoint.getSignature().getName();
//        System.out.println("异常通知:"+name+"方法抛出异常,提示消息为:" +ex.getMessage());
//    }

    /**
     * 5.环绕通知:Around
     *   5.1 在目标方法被调用的各个阶段植入增强逻辑;
     *   5.2 等价于: Before + After + AfterReturning + AfterThrowing 注解的组合;
     *   5.3 通常使用 try ... catch ... finally... 结构;
     *   5.4 既有权限获取目标方法的返回值,又有权限获取异常对象;
     */
    @Around(value = "doTime()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        Object result = null;
        try {
            //1.前置通知
            System.out.println("环绕通知-前置通知");
            //2.目标方法
            result = joinPoint.proceed();
            //3.返回通知
            System.out.println("环绕通知-返回通知");
        } catch (Throwable throwable){
            //4.异常通知
            System.out.println("环绕通知-异常通知");
        } finally {
            //5.后置通知
            System.out.println("环绕通知-后置通知");
        }
        return result;
    }














}
